(function( win ){
    var Base = function(){};

	function _isEmptyObject( obj ) {
		for ( var i in obj ) {
			return false;
		}

		return true;
	}
	function _isArray( obj ) {
		return Object.prototype.toString.call( obj ) === "[object Array]";
	}
	function _isObject( obj ) {
		return Object.prototype.toString.call( obj ) === "[object Object]";
	}

    Base.extend = function( from, target ) {
        var args = Array.prototype.slice.call(arguments);

        if (args.length == 0) return Base;
        if (args.length == 1) target = Base;

        if ( typeof( from ) === "object" ) {
            for (var i in from) {
                if ( _isObject( from[i] ) || _isArray( from[i] ) ) {
                    target[i] = _isArray( from[i] ) ? [] : {};
                    Base.extend( from[i], target[i] );
                } else {
                    target[i] = from[i];
                }
            }
        }
    };
	Base.inherit = function( source, target ) {
		target = target || window;

		if ( typeof(source) === "object" ) {
			for ( var i in source ) {
				if ( source.hasOwnProperty(i) ) {
					target[i] = source[i];
				}
			}
		} else if ( typeof(source) === "function" ) {
			source = source.call(this, Globals);
			Base.inherit(source, target);
		}

		return target;
	};

    var _requireType = ["text/javascript", "text/css", "text/json"];
    Base.extend({
        method: function( name ,fn, target ) {
            if ( arguments.length < 2 ) return;
            if ( !target ) target = Base;

            if ( typeof( name ) === "string" && typeof( fn ) === "function" ) {
                target[name] = fn;
            }

            return target;
        },
        add: function( name, obj, target ) {
            var args = Array.prototype.call(arguments);

            if (!target) target = Base;
            if (args.length == 0) return target;

            if (typeof(name) === "object") {
                obj = name;
                Base.extend( obj );
            } else if (typeof(name) === "string") {
                target[ name ] = obj;
            }

            obj.callback && obj.callback();
        },
        require: function( options ) {
            var head = document.getElementsByTagName("head")[0] || document.documentElement.firstChild,
                newElem;

            if (!options) return this;
            if (!options.url) return this;
            if (!options.type || Base.inArray(options.type, _requireType)) options.type = "text/javascript";

            if (options.type == "text/javascript" || options.type == "text/json"){
                newElem = document.createElement("script");
                newElem.src = "text/javascript";
            } else {
                newElem = document.createElement("link");
                newElem.type = "text/css";
                newElem.rel = "stylesheet";
            }

            if ( newElem.readyState ) {
                newElem.onreadystatechange = function () {
                    if ( newElem.readyState === "loaded" || newElem.readyState === "complete" ) {
                        newElem.onreadystatechange = null;
                        options.callback && options.callback();
                    }
                };
            } else {
                newElem.onload = function () {
                    options.callback && options.callback();
                    newElem.onload = null;
                };
            }

            newElem.src = options.url;
            head.appendChild( newElem );
        }
    });

    Base.extend({
        each: function( obj, callback ) {
            if ( _isArray(obj) ) {
                for ( var i = 0, len = obj.length; len > i; i++ ) {
					callback && callback(i, obj[i]);
				}
            } else {
                for ( var key in obj ) {
					callback && callback(key, obj[key]);
				}
			}
        },
        clone: function(obj) {
            var out = null;

			if ( _isArray(obj) ) {
				out = [];
				this.each(obj, function(i, e) {
					out.push(e);
				});
			} else {
				out = {};
				this.each(obj, function(i, e) {
					out[i] = e;
				});
			}

			return out;
        },
        addEvent: function( el, evt, fn ) {
            if ( el.addEventListener ) {
                el.addEventListener(evt, fn, false);
            } else if ( el.attachEvent ) {
                el.attachEvent("on" + evt, fn);
            } else {
                el[ "on" + evt ] = fn;
            }
        },
        removeEvent: function( el, evt, fn ) {
            if ( el.removeEventListener ) {
                el.removeEventListener(evt, fn, false);
            } else if ( el.detachEvent ) {
                el.detachEvent("on" + evt, fn);
            } else {
                el[ "on" + evt ] = null;
            }
        },
        isArray: function( obj ){
            return Object.prototype.toString.call(obj) === "[object Array]";
        },
        inArray: function( obj ,arr ){
            for (var i = 0;i < arr.length;i++) {
                if (obj == arr[i]) return true;
            }
            return false;
        },
        isFunction: function( obj ){
            return typeof( obj ) === "function";
        },
        isString: function(){
            return typeof( obj ) === "string";
        },
        isBoolean: function(){
            return typeof( obj ) === "boolean";
        },
        isNumber: function(){
            return typeof( obj ) === "number";
        },
        isObject: function(){
            return Object.prototype.toString.call(obj) === "[object Object]";
        },
        getStyle: function( elem, key ) {
            return elem.currentStyle ?
                elem.currentStyle[ key ] :
                (document.defaultView && document.defaultView.getComputedStyle(elem, false)[ key ]) || null;
        },
        getElemByClass: function(className) {// 根据类名得到对象
            var ret = [], elements, classArr;

            if (typeof(document.getElementsByClassName) === "function") {
                ret = document.getElementsByClassName(className);
            } else {
                elements = document.getElementsByTagName("*");
                for (var i = 0, len = elements.length;i < len;i++) {
                    classArr = elements[i].className.split(" ");
                    for (var j = 0, length = classArr.length;j < length;j++) {
                        if (classArr[j] == className) {
                            ret.push(elements[i]);
                            break;
                        }
                    }
                }
            }

            return ret;
        },
        getScrollTop: function(){
            return document.body.scrollTop || document.documentElement.scrollTop;
        },
        getScrollHeight: function(){
            return document.body.scrollHeight || document.documentElement.scrollHeight;
        },
        getClientHeight: function(){
            return document.body.clientHeight || document.documentElement.clientHeight;
        },
        getClientWidth: function(){
            return document.body.clientWidth || document.documentElement.clientWidth;
        },
        // 格式化字符串
        stringFormat: function(str, arr) {
            if (!str) return false;
            if (!arr || (arr && !(arr instanceof Array))) return false;

            return str.replace(/\{(\d+)\}/g, function(m,i){
                return arr[i];
            });
        }
    });

    win.Base = Base;
})( window );